# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: jhkim, jaewon

import datetime
import logging
from typing import Optional

from tornado.ioloop import IOLoop

import coin.flow.subscriber as flow_subscriber
from coin.base.param_util import to_list
from coin.flow.simple_queue import SimpleQueue

from coin.strategy.mm.bitflyer_v1.feed_arb import BitflyerFeedArbSubsystem


class BitflyerLiveEnvironment(object):
  def __init__(self,
               *,
               feed_product,
               ioloop=None,
               queue=None,
               flow_sub=None,
               logger=None,
               fs_config=None):
    self._logger = logger or logging.getLogger('Bitflyer')

    self._feed_products = to_list(feed_product)
    self.ioloop = ioloop or IOLoop.current()
    self.queue = queue or SimpleQueue('queue')
    self.flow_sub = flow_sub or flow_subscriber.from_queue(self.queue)

    self._num_feed_worker = fs_config.arbitration_connection_count if fs_config else 2
    self._worker_ids = [(wid + 1) for wid in range(self._num_feed_worker)]
    self._feed_subsystem = None
    self.on_book_reset_callback = []

  def _init_feed_subsystem(self):
    self._logger.info('Initializing feed...')
    self._feed_subsystem = BitflyerFeedArbSubsystem(self._feed_products,
                                                    self._on_book_reset,
                                                    worker_ids=self._worker_ids)
    self._feed_subsystem.start(self.ioloop, self.queue, self.flow_sub)

  def _on_book_reset(self, book_builder_name, book_builder):
    for callback in self.on_book_reset_callback:
      callback(book_builder_name, book_builder)

  def start(self):
    self.ioloop.add_callback(self._init_feed_subsystem)

  def loop(self, exit_after: Optional[datetime.timedelta] = None):
    if exit_after is not None:
      self.ioloop.add_timeout(exit_after, self.ioloop.stop)
    self.ioloop.start()
